/**@file

 @copyright
  INTEL CONFIDENTIAL
  Copyright 2012 - 2016 Intel Corporation.

  The source code contained or described herein and all documents related to the
  source code ("Material") are owned by Intel Corporation or its suppliers or
  licensors. Title to the Material remains with Intel Corporation or its suppliers
  and licensors. The Material may contain trade secrets and proprietary and
  confidential information of Intel Corporation and its suppliers and licensors,
  and is protected by worldwide copyright and trade secret laws and treaty
  provisions. No part of the Material may be used, copied, reproduced, modified,
  published, uploaded, posted, transmitted, distributed, or disclosed in any way
  without Intel's prior express written permission.

  No license under any patent, copyright, trade secret or other intellectual
  property right is granted to or conferred upon you by disclosure or delivery
  of the Materials, either expressly, by implication, inducement, estoppel or
  otherwise. Any license under such intellectual property rights must be
  express and approved by Intel in writing.

  Unless otherwise agreed by Intel in writing, you may not remove or alter
  this notice or any other notice embedded in Materials by Intel or
  Intel's suppliers or licensors in any way.

  This file contains 'Framework Code' and is licensed as such under the terms
  of your license agreement with Intel or your vendor. This file may not be 
  modified, except as allowed by additional terms of your license agreement.

@par Specification Reference:

**/

#ifndef _VIRTUAL_KEYBOARD_H_
#define _VIRTUAL_KEYBOARD_H_

#include <Uefi.h>
#include <Library/BaseMemoryLib.h>
#include <Library/I2cDriverLib.h>
#include <Protocol/AbsolutePointer.h>
#include <Protocol/GraphicsOutput.h>
#include <Protocol/SimpleTextIn.h>
#include <Library/UefiRuntimeServicesTableLib.h>
#include <Protocol/SimpleTextInEx.h>
#include <Protocol/VirtualKeyboard.h>
#include <Guid/ConsoleInDevice.h>
#include <Protocol/ComponentName.h>
#include <Protocol/ComponentName2.h>
#include "ComponentName.h"
extern EFI_GUID gEfiTouchPanelGuid;

///
/// Debug raw data points
///
#define DEBUG_VK_POINTS               0x40000000

///
/// Debug data point scaling
///
#define DEBUG_VK_POINT_SCALING        0x20000000

///
/// Debug key press
///
#define DEBUG_VK_KEYS                 0x10000000

///
/// Debug routine entry and exit
///
#define DEBUG_VK_ROUTINE_ENTRY_EXIT   0x08000000

///
/// Display the graphics info
///
#define DEBUG_VK_GRAPHICS_INFO        0x04000000

///
/// Display the timer entry and exit
///
#define DEBUG_VK_TIMER_ENTRY_EXIT     0x00100000

///
/// "VKey"
///
// #define VK_SIGNATURE            0x79654b56
#define VK_SIGNATURE  SIGNATURE_32 ('V', 'K', 'e', 'y')


///
/// Poll interval
///
#define VK_POLL_INTERVAL    (100 * 1000)

///
/// Define the touch timeout in poll intervals
///
#define VK_TOUCH_TIMEOUT    1
#define VK_REPET_TIMEOUT    5
#define MAX_VKBD_PAGE_NUM   2

///
/// TPL used to synchronize add/remove from list
///
#define TPL_VK_SYNC             TPL_CALLBACK

extern EFI_DRIVER_BINDING_PROTOCOL  gVirtualKeyboardDriverBinding;
extern EFI_COMPONENT_NAME_PROTOCOL  gVirtualKeyboardComponentName;
extern EFI_COMPONENT_NAME2_PROTOCOL gVirtualKeyboardComponentName2;
extern EFI_GUID                     gEfiNormalSetupGuid;

typedef struct _VK_CONTEXT VK_CONTEXT;

///
/// Define some colors
///
#define COLOR_BLACK         0
#define COLOR_WHITE         0x00FFFFFF
#define COLOR_RED           0x00FF0000
#define COLOR_GREEN         0x0000FF00
#define COLOR_BLUE          0x000000FF 
#define COLOR_DARK_GRAY     0x00303030
#define COLOR_LIGHT_GRAY    0x00989898

///
/// Dimension of an array ( number of elements )
///
#define DIM(x)      ( sizeof ( x ) / sizeof ( x [ 0 ]))

///
/// Define Key buffer
///
#define MAX_KEY_BUF_SIZE  32

///
/// Define the keyboard keys
///
typedef struct {
  CHAR8  Key;
  UINT64 MinX;
  UINT64 MaxX;
} KEYBOARD_KEY;

///
/// Define a row of keys
///
typedef struct {
  KEYBOARD_KEY *Keys;
  UINTN        NumberOfKeys;
  UINT64       MinY;
  UINT64       MaxY;
} KEYBOARD_ROW;

typedef struct {
  UINT64               ImageSize;
  EFI_PHYSICAL_ADDRESS ImageAddr;
} BMP_VARIABLE_STRUCT;

#pragma pack (1)
typedef struct {
  UINT32   *FontPtr;
  UINT8    AciiCode;
  UINT8    NumOfRow;
} FONT_INFO;

typedef struct {
  UINT32   Start_X;
  UINT32   Start_Y;
  UINT32   End_X;
  UINT32   End_Y;
} DISP_INFO;

typedef struct {
  UINT32   Start_X;
  UINT32   Start_Y;
  UINT32   End_X;
  UINT32   End_Y;
} TOUCH_INFO;

typedef struct {
  FONT_INFO   *FontPtr;
  DISP_INFO   Disp;
  TOUCH_INFO  TouchAddr;
} KEY_INFO;
#pragma pack()

/**
  Virtual Keyboard context

**/
struct _VK_CONTEXT {
  ///
  /// Structure identification
  ///
  UINTN Signature;

  ///
  /// Upper level API
  ///
  EFI_SIMPLE_TEXT_INPUT_PROTOCOL SimpleTextIn;
  
  ///
  /// Simple Text In EX
  ///
  EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL SimpleInputEx;
  
  ///
  /// Display keyboard on the screen 
  ///
  VIRTUAL_KEYBOARD_PROTOCOL    VkbdProtocol;
  
  ///
  /// Flag when the last poll indicated a touch event
  ///
  BOOLEAN TouchActive;

  ///
  /// Count down timer to detect inactivity
  ///
  UINTN InactiveCountDown;

  ///
  /// Time to poll for touch input
  ///
  EFI_EVENT TimerEvent;

  ///
  /// COntroll Handle
  ///
  EFI_HANDLE Controller;

  ///
  /// Frame buffer address
  ///
  UINT32 * FrameBuffer;

  ///
  /// Display coordinates
  ///
  UINT32 DisplayLeft;
  UINT32 DisplayRight;
  UINT32 DisplayTop;
  UINT32 DisplayBottom;
  INT32 XIncrement;
  INT32 XExtra;
  INT32 XSign;
  INT32 YIncrement;
  INT32 YExtra;
  INT32 YSign;

  ///
  /// Touch coordinates
  ///
  UINT64 TouchLeft;
  UINT64 TouchRight;
  UINT64 TouchTop;
  UINT64 TouchBottom;

  ///
  /// Key state
  ///
  BOOLEAN KeyPressed;

  ///
  /// Display the keyboard
  ///
  BOOLEAN DisplayKeyboard;

  ///
  /// Display the keyboard
  ///
  BOOLEAN ShowTheKeyboard;

  ///
  /// Lower level APIs
  ///
  EFI_ABSOLUTE_POINTER_PROTOCOL *AbsolutePointer;
  EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;

  //
  // Keyboard Image address
  //
  VOID       *XmanPtr;
  UINT32     NumOfKeysInfo;
  
  //
  // KeyBuffer
  //
  UINT8      AltKeyBuf[MAX_KEY_BUF_SIZE];
  UINT16     Keybuffer[MAX_KEY_BUF_SIZE];
  UINT8      KeyStartIndex;
  UINT8      KeyEndIndex;
  UINT16     KeyTouchedTimeOut;
  UINT8      ShiftKeyFlag;
  UINT8      PageNumber;
};

///
/// Locate VK_CONTEXT from protocol
///
#define VK_CONTEXT_FROM_PROTOCOL(a) CR (a, VK_CONTEXT, SimpleTextIn, VK_SIGNATURE)
#define VK_CONTEXT_FROM_SIMPLETEXTINEX_PROTOCOL(a) CR (a, VK_CONTEXT, SimpleInputEx, VK_SIGNATURE)
#define VK_CONTEXT_FROM_VKBD_PROTOCOL(a) CR (a, VK_CONTEXT, VkbdProtocol, VK_SIGNATURE)



/**
  Start the driver

  This routine allocates the necessary resources for the driver.

  This routine is called by VirtualKeyboardDriverStart to complete the driver
  initialization.

  @param[in] VkContext      Address of an VK_CONTEXT structure
  @param[in] Controller     Handle to the controller

  @retval EFI_SUCCESS       Driver API properly initialized
  
**/
EFI_STATUS
VkApiStart (
  IN VK_CONTEXT *VkContext,
  IN EFI_HANDLE Controller
  );

/**
  Stop the driver

  This routine releases the resources allocated by VkApiStart.

  This routine is called by VirtualKeyboardDriverStop to initiate the driver
  shutdown.

  @param[in] VkContext      Address of an VK_CONTEXT structure

**/
VOID
VkApiStop (
  IN VK_CONTEXT *VkContext
  );

/**
  Reset the input device and optionally run diagnostics

  @param  This                 Protocol instance pointer.
  @param  ExtendedVerification Driver may perform diagnostics on reset.

  @retval EFI_SUCCESS          The device was reset.
  @retval EFI_DEVICE_ERROR     The device is not functioning properly and could not be reset.

**/
EFI_STATUS
EFIAPI
VkReset (
  IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
  IN BOOLEAN ExtendedVerification
  );

/**
  Reads the next keystroke from the input device. The WaitForKey Event can 
  be used to test for existence of a keystroke via WaitForEvent () call.

  @param  This Protocol instance pointer.
  @param  Key  Driver may perform diagnostics on reset.

  @retval EFI_SUCCESS      The keystroke information was returned.
  @retval EFI_NOT_READY    There was no keystroke data available.
  @retval EFI_DEVICE_ERROR The keystroke information was not returned due to
                           hardware errors.

**/
EFI_STATUS
EFIAPI
VkReadKeyStroke (
  IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
  OUT EFI_INPUT_KEY *Key
  );

/**
  Draw key board on the display

  @param  VkContext             Graphic Protocol for draw the alphabet.
  @param  StartX                The button upper-left X location.
  @param  StartY                The button upper-left Y location.
  @param  EndX                  The button lower-right X location.
  @param  EndY                  The button lower-right Y location.
  @param  SetColor              Set key button color.

  @retval EFI_SUCCESS           Draw keyboard was done.
  @retval EFI_UNSUPPORTED       Did not get key mapping table.

**/   
EFI_STATUS
DrawKeyboardLayout( 
  IN VK_CONTEXT *VkContext
);

/**
  Clear the key button

  @param  VkContext             Code context.

  @retval EFI_SUCCESS           Clear rectangle is done.

**/  
EFI_STATUS
HiddenRectangle ( 
  IN VK_CONTEXT *VkContext
);

/**
  Draw the key button

  @param  GraphicsOutput        Graphic Protocol for draw the alphabet.
  @param  StartX                The button upper-left X location.
  @param  StartY                The button upper-left Y location.
  @param  EndX                  The button lower-right X location.
  @param  EndY                  The button lower-right Y location.
  @param  SetColor              Set key button color.

  @retval EFI_SUCCESS           Draw the alphabet is done.

**/   
EFI_STATUS
DrawRectangle (
  IN  EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput,
  IN  UINTN  StartX,
  IN  UINTN  StartY,
  IN  UINTN  EndX,
  IN  UINTN  EndY,
  IN  UINTN  LineWidth
  );

/**
  Draw word in the Key button

  @param  GraphicsOutput        Graphic Protocol for draw the alphabet.
  @param  StartX                The button upper-left X location.
  @param  StartY                The button upper-left Y location.
  @param  EndX                  The button lower-right X location.
  @param  EndY                  The button lower-right Y location.
  @param  *FontPtr              It is bit map structure for the alphabet drawing display.
  @param  Color                 Set the alphabet color.
  @param  Flag                  Flag set to 1, draw the color to the alphabet.
                                Flag set to 0, reverse the Flag set to 0

  @retval EFI_SUCCESS           Draw the alphabet is done.
  @retval EFI_INVALID_PARAMETER The FontPtr is NULL.

**/ 
EFI_STATUS
DrawCharacter (
  IN   EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput,
  IN   UINT32                       StartX,
  IN   UINT32                       StartY,
  IN   UINT32                       EndX,
  IN   UINT32                       EndY,
  IN   UINT32                       *FontPtr,
  IN   UINT32                       Color,
  IN   UINT8                        Flag
  );


/**
  Resets the input device hardware.

  The Reset() function resets the input device hardware. As part
  of initialization process, the firmware/device will make a quick
  but reasonable attempt to verify that the device is functioning.
  If the ExtendedVerification flag is TRUE the firmware may take
  an extended amount of time to verify the device is operating on
  reset. Otherwise the reset operation is to occur as quickly as
  possible. The hardware verification process is not defined by
  this specification and is left up to the platform firmware or
  driver to implement.

  @param This                 A pointer to the EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL instance.

  @param ExtendedVerification Indicates that the driver may perform a more exhaustive
                              verification operation of the device during reset.

  @retval EFI_SUCCESS         The device was reset.
  @retval EFI_DEVICE_ERROR    The device is not functioning correctly and could not be reset.

**/
EFI_STATUS
EFIAPI
VkKeyboardResetEx (
  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,
  IN BOOLEAN                            ExtendedVerification
  );

/**
  Reads the next keystroke from the input device.

  @param  This                   Protocol instance pointer.
  @param  KeyData                A pointer to a buffer that is filled in with the keystroke
                                 state data for the key that was pressed.

  @retval EFI_SUCCESS            The keystroke information was returned.
  @retval EFI_NOT_READY          There was no keystroke data available.
  @retval EFI_DEVICE_ERROR       The keystroke information was not returned due to
                                 hardware errors.
  @retval EFI_INVALID_PARAMETER  KeyData is NULL.

**/  
EFI_STATUS
EFIAPI
VkKeyboardReadKeyStrokeEx (
  IN  EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
  OUT EFI_KEY_DATA                      *KeyData
  );

/**
  Set certain state for the input device.

  @param  This                    Protocol instance pointer.
  @param  KeyToggleState          A pointer to the EFI_KEY_TOGGLE_STATE to set the
                                  state for the input device.

  @retval EFI_SUCCESS             The device state was set appropriately.
  @retval EFI_DEVICE_ERROR        The device is not functioning correctly and could
                                  not have the setting adjusted.
  @retval EFI_UNSUPPORTED         The device does not support the ability to have its state set.
  @retval EFI_INVALID_PARAMETER   KeyToggleState is NULL.

**/  
EFI_STATUS
EFIAPI
VkKeyboardSetState (
  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,
  IN EFI_KEY_TOGGLE_STATE               *KeyToggleState
  );

/**
  Register a notification function for a particular keystroke for the input device.

  @param  This                        Protocol instance pointer.
  @param  KeyData                     A pointer to a buffer that is filled in with the keystroke
                                      information data for the key that was pressed.
  @param  KeyNotificationFunction     Points to the function to be called when the key
                                      sequence is typed specified by KeyData.
  @param  NotifyHandle                Points to the unique handle assigned to the registered notification.

  @retval EFI_SUCCESS                 The notification function was registered successfully.
  @retval EFI_OUT_OF_RESOURCES        Unable to allocate resources for necessary data structures.
  @retval EFI_INVALID_PARAMETER       KeyData or NotifyHandle or KeyNotificationFunction is NULL.

**/  
EFI_STATUS
EFIAPI
VkKeyboardRegisterKeyNotify (
  IN  EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,
  IN  EFI_KEY_DATA                       *KeyData,
  IN  EFI_KEY_NOTIFY_FUNCTION            KeyNotificationFunction,
  OUT EFI_HANDLE                         *NotifyHandle
  );

/**
  Remove a registered notification function from a particular keystroke.

  @param  This                      Protocol instance pointer.
  @param  NotificationHandle        The handle of the notification function being unregistered.

  @retval EFI_SUCCESS              The notification function was unregistered successfully.
  @retval EFI_INVALID_PARAMETER    The NotificationHandle is invalid

**/  
EFI_STATUS
EFIAPI
VkKeyboardUnregisterKeyNotify (
  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,
  IN EFI_HANDLE                         NotificationHandle
  );


/**
  Diaplay VKBD on the screen.

  @param  This                      Protocol instance pointer.

  @retval EFI_SUCCESS              The notification function was unregistered successfully.
  @retval EFI_INVALID_PARAMETER    The NotificationHandle is invalid

**/
EFI_STATUS
EFIAPI
ShowVkbdCallBack ( 
  IN VIRTUAL_KEYBOARD_PROTOCOL        *This
  );  
#endif  //  _VIRTUAL_KEYBOARD_H
